home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_dos.lha / dos / sphsrc / sph_clip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  8.4 KB  |  333 lines

  1. #include "HEADERS.h"
  2.    
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include <math.h>
  6.    
  7. #include "sphigslocal.h"
  8.    
  9.    
  10. void bound(view_spec *vs, obj *current );
  11.  
  12. vertex_index add_global_point(view_spec *vs, MAT3hvec p );
  13.  
  14. #define FRONT 1
  15. #define BACK  2
  16.  
  17. static void clip_generic (view_spec *vs,  obj *current, double wall, int WHICH);
  18. static void interpolate_point( MAT3hvec p1, MAT3hvec p2, double z, MAT3hvec p3 );
  19.  
  20.  
  21. #define clip_front(V,C,W)   clip_generic((V),(C),(W), FRONT)
  22. #define clip_back(V,C,W)   clip_generic((V),(C),(W), BACK)
  23.  
  24.  
  25. void SPH__clip (view_spec *vs)
  26. {
  27.    obj *              current;
  28.    obj *              prev;
  29.    MAT3hvec           min;
  30.    MAT3hvec           max;
  31.    MAT3hvec           previous;
  32.    double             front;
  33.    double             back;
  34.    MAT3hvec *         uvnVertices;
  35.    
  36.    assert( vs != NULL );
  37.    front = vs->frontPlaneDistance;
  38.    back = vs->backPlaneDistance;
  39.    
  40.    if( vs->objects == NULL )
  41.       return;
  42.    
  43.    assert( vs->vm_matrix != NULL );
  44.    assert( vs->uvnVertices != NULL );
  45.    uvnVertices = vs->uvnVertices;
  46.    assert( back < front );
  47.    
  48.    prev = NULL;
  49.    current = vs->objects;
  50.    while( current != NULL ) {
  51.       
  52.       assert( current->next != current );
  53.       
  54.       bound(vs, current );
  55.       assert( current->min[X] <= current->max[X] );
  56.       assert( current->min[Y] <= current->max[Y] );
  57.       assert( current->min[Z] <= current->max[Z] );
  58.       
  59.       MAT3_COPY_VEC( min, current->min );
  60.       MAT3_COPY_VEC( max, current->max );
  61.       
  62.       /* remove obj if z bounds are behind "back" or in front of "front" */
  63.       
  64.       /* this will take care of points and text */
  65.       
  66.       if( max[Z] < back || min[Z] > front ) {
  67.      if( prev == NULL )
  68.         vs->objects = current->next;
  69.      else
  70.         prev->next = current->next;
  71.      current = current->next;
  72.      continue;
  73.       }
  74.       
  75.       /* only clip object if it's intersecting the front or back plane */
  76.       
  77.       if( max[Z] > front || min[Z] < back ) {
  78.      
  79.      /* handle line intersection with front and back planes */
  80.      
  81.      if( current->type == objLine ) {
  82.         
  83.         /* special case lines parallel to X-Y */
  84.         
  85.         if( min[X] == max[X] || min[Y] == max[Y] ) {
  86.            min[Z] = MAX( min[Z], back );
  87.            max[Z] = MIN( max[Z], front );
  88.            MAT3_COPY_VEC( current->min, min );
  89.            MAT3_COPY_VEC( current->max, max );
  90.            
  91.         } else {
  92.            if( max[Z] > back && back > min[Z] ) {
  93.           fprintf (stderr, "CALL TO interpolate_point IS WEIRD (clip.c,1)\n");
  94.           sleep(15);
  95.           exit(1);
  96.           /* interpolate_point( max[Z], min[Z], back, min[Z] ); */
  97.            }
  98.            if( max[Z] > front && front > min[Z] ) {
  99.           fprintf (stderr, "CALL TO interpolate_point IS WEIRD (clip.c,2)\n");
  100.           sleep(15);
  101.           exit(1);
  102.           /* interpolate_point( min[Z], max[Z], back, max[Z] ); */
  103.            }
  104.         }
  105.         
  106.      } else if( current->type == objFace ) {
  107.         
  108.         /* handle plane intersection with front and back planes */
  109.         
  110.         assert( current->data.face.numPoints >= 3 );
  111.         
  112.         if( max[Z] > front )
  113.            clip_front( vs, current, front );
  114.         
  115.         if( min[Z] < back )
  116.            clip_back( vs, current, back );
  117.         
  118.      }
  119.       }
  120.       
  121.       prev = current;
  122.       current = current->next;
  123.    }
  124. }
  125.  
  126.  
  127. void bound(view_spec *vs, obj *current )
  128.  
  129. {
  130.    register int       i;
  131.    MAT3hvec           p;
  132.    MAT3hvec           max;
  133.    MAT3hvec           min;
  134.    
  135.    assert( vs != NULL );
  136.    assert( vs->uvnVertices != NULL );
  137.    assert( current != NULL );
  138.    
  139.    switch( current->type ) {
  140.     case objFace:
  141.       
  142.       max[X] = max[Y] = max[Z] = -HUGE_VAL;
  143.       min[X] = min[Y] = min[Z] = HUGE_VAL;
  144.       
  145.       for( i = 0; i < current->data.face.numPoints; i++ ) {
  146.      MAT3_COPY_VEC (p, 
  147.             (vs->uvnVertices)
  148.                [current->data.face.points[i]] );
  149.      if( p[X] > max[X] )
  150.         max[X] = p[X];
  151.      if( p[Y] > max[Y] )
  152.         max[Y] = p[Y];
  153.      if( p[Z] > max[Z] )
  154.         max[Z] = p[Z];
  155.      
  156.      if( p[X] < min[X] )
  157.         min[X] = p[X];
  158.      if( p[Y] < min[Y] )
  159.         min[Y] = p[Y];
  160.      if( p[Z] < min[Z] ) 
  161.         min[Z] = p[Z];
  162.       }
  163.       MAT3_COPY_VEC( current->min, min );
  164.       MAT3_COPY_VEC( current->max, max );
  165.       break;
  166.       
  167.     case objLine:
  168.       for (i=X; i<=Z; i++) {
  169.          min[i] = 
  170.         MIN (current->data.line.end1[i], current->data.line.end2[i]);
  171.      max[i] = 
  172.         MAX ( current->data.line.end1[i], current->data.line.end2[i]);
  173.       }
  174.       break;
  175.       
  176.     case objPoint:
  177.       MAT3_COPY_VEC( current->max, current->min );
  178.       break;
  179.       
  180.     case objText:
  181.       current->max[Z] = current->min[Z];
  182.       break;
  183.       
  184.    }
  185. }
  186.  
  187.  
  188.  
  189. static void clip_generic (view_spec *vs,  obj *current, double wall, int WHICH)
  190. {
  191.    int                last_zone;
  192.    int                current_zone;
  193.    int                index1, index2;
  194.    MAT3hvec           new_point;
  195.    MAT3hvec           last_point;
  196.    MAT3hvec           current_point;
  197.    int                new_global_index;
  198.    vertex_index *     new_face_points;
  199.    vertex_index *     points;
  200.    MAT3hvec *         uvnVertices;
  201.    int                i;
  202.    boolean            final_point, flag;
  203.    
  204.    assert( vs != NULL );
  205.    assert( vs->uvnVertices != NULL );
  206.    assert( current != NULL );
  207.    
  208.    uvnVertices = vs->uvnVertices;
  209.    
  210.    /* go through all the points */
  211.    
  212.    index2 = 0;
  213.    index1 = 0;
  214.    
  215.    new_face_points = (vertex_index *) 
  216.       FALLOCalloc(vs->objectChunk, 
  217.           sizeof(vertex_index) * 
  218.           (current->data.face.numPoints+2), FALLOC__DONT_ZERO);
  219.    assert( new_face_points != NULL );
  220.    
  221.    points = & current->data.face.points[0];
  222.    assert( points != NULL );
  223.    
  224.    MAT3_COPY_VEC( last_point, uvnVertices[ points[ index1 ] ] );
  225.  
  226.    flag = FALSE;
  227.    if (WHICH == BACK) {   
  228.       if (last_point[Z] < wall) {last_zone = -1; flag=TRUE;}
  229.    }
  230.    else {
  231.       if (last_point[Z] > wall) {last_zone = 1; flag=TRUE;}
  232.    }
  233.    if ( ! flag) {
  234.       last_zone = 0;
  235.       new_face_points[ index2 ] = points[ index1 ];
  236.       index2 ++;
  237.    }
  238.    
  239.    final_point = FALSE;
  240.    for( index1 = 1; index1 <= current->data.face.numPoints && ! final_point; index1 ++ ) {
  241.       
  242.       if( index1 == current->data.face.numPoints ) {
  243.      final_point = TRUE;
  244.      MAT3_COPY_VEC( current_point, uvnVertices[ points[ 0 ] ] );
  245.       } else
  246.      MAT3_COPY_VEC( current_point, uvnVertices[ points[ index1 ] ] );
  247.       
  248.       flag = FALSE;
  249.       if (WHICH == BACK) {   
  250.          if (current_point[Z] < wall) {current_zone = -1; flag=TRUE;}
  251.       }
  252.       else {
  253.          if (current_point[Z] > wall) {current_zone = 1; flag=TRUE;}
  254.       }
  255.       if ( ! flag)
  256.      current_zone = 0;
  257.       
  258.  
  259.       if( current_zone != last_zone ) {
  260.      interpolate_point( last_point, current_point, wall, new_point );
  261.      new_global_index = add_global_point( vs, new_point );
  262.      new_face_points[ index2 ] = new_global_index;
  263.      index2 ++;
  264.       }
  265.       
  266.       if( current_zone == 0 && ! final_point ) {
  267.      new_face_points[ index2 ] = points[ index1 ];
  268.      index2 ++;
  269.       }
  270.       
  271.       MAT3_COPY_VEC( last_point, current_point );
  272.       last_zone = current_zone;
  273.    }
  274.    
  275.    current->data.face.points = new_face_points;
  276.    current->data.face.numPoints = index2;
  277.    
  278. }
  279.  
  280. static void interpolate_point( MAT3hvec p1, MAT3hvec p2, double z, MAT3hvec p3 )
  281. {
  282.    double             yz_slope;
  283.    double             xz_slope;
  284.    
  285.    yz_slope = ( p2[Y] - p1[Y] ) / ( p2[Z] - p1[Z] );
  286.    xz_slope = ( p2[X] - p1[X] ) / ( p2[Z] - p1[Z] );
  287.    
  288.    p3[Z] = z;
  289.    p3[X] = p1[X] + xz_slope * ( z - p1[Z] );
  290.    p3[Y] = p1[Y] + yz_slope * ( z - p1[Z] );
  291. }
  292.  
  293.  
  294. vertex_index add_global_point(view_spec *vs, MAT3hvec p )
  295.  
  296. {
  297.    assert( vs != NULL );
  298.    assert( vs->uvnVertices != NULL );
  299.    assert( vs->npcVertices != NULL );
  300.    assert( vs->vertexArraySize != 0 );
  301.    assert( vs->vertexCount <= vs->vertexArraySize );
  302.    
  303.    if( vs->vertexCount == vs->vertexArraySize ) {
  304.       vs->vertexArraySize /= 2;
  305.       vs->vertexArraySize *= 3;
  306.       vs->uvnVertices = 
  307.      (MAT3hvec*) 
  308.         realloc (vs->uvnVertices, 
  309.              (MALLOCARGTYPE)(vs->vertexArraySize*sizeof(MAT3hvec)));
  310.       if (vs->uvnVertices == NULL) 
  311.      SPH__error (ERR_MALLOC);
  312.       vs->npcVertices = 
  313.      (MAT3hvec *) 
  314.         realloc (vs->npcVertices, 
  315.              (MALLOCARGTYPE)(vs->vertexArraySize*sizeof(MAT3hvec)));
  316.       if (vs->npcVertices == NULL) 
  317.      SPH__error (ERR_MALLOC);
  318.    }
  319.    
  320.    MAT3_COPY_VEC( (vs->uvnVertices)[ vs->vertexCount ], p );
  321.    ((vs->uvnVertices)[ vs->vertexCount ])[3] = 1;
  322.    
  323.    MAT3mult_hvec
  324.       (vs->npcVertices[ vs->vertexCount ], 
  325.        vs->uvnVertices[ vs->vertexCount ],
  326.        vs->vm_matrix, 1 );
  327.    (vs->npcVertices[ vs->vertexCount ])[Z] *= -1;
  328.    
  329.    vs->vertexCount ++;
  330.    
  331.    return( vs->vertexCount - 1 );
  332. }
  333.